<!doctype html>

<html>
<head>
  <link rel="shortcut icon" href="static/images/favicon.ico" type="image/x-icon">
  <title>utils.js (Closure Library API Documentation - JavaScript)</title>
  <link rel="stylesheet" href="static/css/base.css">
  <link rel="stylesheet" href="static/css/doc.css">
  <link rel="stylesheet" href="static/css/sidetree.css">
  <link rel="stylesheet" href="static/css/prettify.css">

  <script>
     var _staticFilePath = "static/";
     var _typeTreeName = "goog";
     var _fileTreeName = "Source";
  </script>

  <script src="static/js/doc.js">
  </script>


  <meta charset="utf8">
</head>

<body onload="grokdoc.onLoad();">

<div id="header">
  <div class="g-section g-tpl-50-50 g-split">
    <div class="g-unit g-first">
      <a id="logo" href="index.html">Closure Library API Documentation</a>
    </div>

    <div class="g-unit">
      <div class="g-c">
        <strong>Go to class or file:</strong>
        <input type="text" id="ac">
      </div>
    </div>
  </div>
</div>

<div class="clear"></div>

<h2><a href="closure_goog_uri_utils.js.html">utils.js</a></h2>

<pre class="prettyprint lang-js">
<a name="line1"></a>// Copyright 2008 The Closure Library Authors. All Rights Reserved.
<a name="line2"></a>//
<a name="line3"></a>// Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
<a name="line4"></a>// you may not use this file except in compliance with the License.
<a name="line5"></a>// You may obtain a copy of the License at
<a name="line6"></a>//
<a name="line7"></a>//      http://www.apache.org/licenses/LICENSE-2.0
<a name="line8"></a>//
<a name="line9"></a>// Unless required by applicable law or agreed to in writing, software
<a name="line10"></a>// distributed under the License is distributed on an &quot;AS-IS&quot; BASIS,
<a name="line11"></a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a name="line12"></a>// See the License for the specific language governing permissions and
<a name="line13"></a>// limitations under the License.
<a name="line14"></a>
<a name="line15"></a>/**
<a name="line16"></a> * @fileoverview Simple utilities for dealing with URI strings.
<a name="line17"></a> *
<a name="line18"></a> * This is intended to be a lightweight alternative to constructing goog.Uri
<a name="line19"></a> * objects.  Whereas goog.Uri adds several kilobytes to the binary regardless
<a name="line20"></a> * of how much of its functionality you use, this is designed to be a set of
<a name="line21"></a> * mostly-independent utilities so that the compiler includes only what is
<a name="line22"></a> * necessary for the task.  Estimated savings of porting is 5k pre-gzip and
<a name="line23"></a> * 1.5k post-gzip.  To ensure the savings remain, future developers should
<a name="line24"></a> * avoid adding new functionality to existing functions, but instead create
<a name="line25"></a> * new ones and factor out shared code.
<a name="line26"></a> *
<a name="line27"></a> * Many of these utilities have limited functionality, tailored to common
<a name="line28"></a> * cases.  The query parameter utilities assume that the parameter keys are
<a name="line29"></a> * already encoded, since most keys are compile-time alphanumeric strings.  The
<a name="line30"></a> * query parameter mutation utilities also do not tolerate fragment identifiers.
<a name="line31"></a> *
<a name="line32"></a> * By design, these functions can be slower than goog.Uri equivalents.
<a name="line33"></a> * Repeated calls to some of functions may be quadratic in behavior for IE,
<a name="line34"></a> * although the effect is somewhat limited given the 2kb limit.
<a name="line35"></a> *
<a name="line36"></a> * One advantage of the limited functionality here is that this approach is
<a name="line37"></a> * less sensitive to differences in URI encodings than goog.Uri, since these
<a name="line38"></a> * functions modify the strings in place, rather than decoding and
<a name="line39"></a> * re-encoding.
<a name="line40"></a> *
<a name="line41"></a> * Uses features of RFC 3986 for parsing/formatting URIs:
<a name="line42"></a> *   http://gbiv.com/protocols/uri/rfc/rfc3986.html
<a name="line43"></a> *
<a name="line44"></a> * @author gboyer@google.com (Garrett Boyer) - The &quot;lightened&quot; design.
<a name="line45"></a> * @author msamuel@google.com (Mike Samuel) - Domain knowledge and regexes.
<a name="line46"></a> */
<a name="line47"></a>
<a name="line48"></a>goog.provide(&#39;goog.uri.utils&#39;);
<a name="line49"></a>goog.provide(&#39;goog.uri.utils.ComponentIndex&#39;);
<a name="line50"></a>goog.provide(&#39;goog.uri.utils.QueryArray&#39;);
<a name="line51"></a>goog.provide(&#39;goog.uri.utils.QueryValue&#39;);
<a name="line52"></a>goog.provide(&#39;goog.uri.utils.StandardQueryParam&#39;);
<a name="line53"></a>
<a name="line54"></a>goog.require(&#39;goog.asserts&#39;);
<a name="line55"></a>goog.require(&#39;goog.string&#39;);
<a name="line56"></a>goog.require(&#39;goog.userAgent&#39;);
<a name="line57"></a>
<a name="line58"></a>
<a name="line59"></a>/**
<a name="line60"></a> * Character codes inlined to avoid object allocations due to charCode.
<a name="line61"></a> * @enum {number}
<a name="line62"></a> * @private
<a name="line63"></a> */
<a name="line64"></a>goog.uri.utils.CharCode_ = {
<a name="line65"></a>  AMPERSAND: 38,
<a name="line66"></a>  EQUAL: 61,
<a name="line67"></a>  HASH: 35,
<a name="line68"></a>  QUESTION: 63
<a name="line69"></a>};
<a name="line70"></a>
<a name="line71"></a>
<a name="line72"></a>/**
<a name="line73"></a> * Builds a URI string from already-encoded parts.
<a name="line74"></a> *
<a name="line75"></a> * No encoding is performed.  Any component may be omitted as either null or
<a name="line76"></a> * undefined.
<a name="line77"></a> *
<a name="line78"></a> * @param {?string=} opt_scheme The scheme such as &#39;http&#39;.
<a name="line79"></a> * @param {?string=} opt_userInfo The user name before the &#39;@&#39;.
<a name="line80"></a> * @param {?string=} opt_domain The domain such as &#39;www.google.com&#39;, already
<a name="line81"></a> *     URI-encoded.
<a name="line82"></a> * @param {(string|number|null)=} opt_port The port number.
<a name="line83"></a> * @param {?string=} opt_path The path, already URI-encoded.  If it is not
<a name="line84"></a> *     empty, it must begin with a slash.
<a name="line85"></a> * @param {?string=} opt_queryData The URI-encoded query data.
<a name="line86"></a> * @param {?string=} opt_fragment The URI-encoded fragment identifier.
<a name="line87"></a> * @return {string} The fully combined URI.
<a name="line88"></a> */
<a name="line89"></a>goog.uri.utils.buildFromEncodedParts = function(opt_scheme, opt_userInfo,
<a name="line90"></a>    opt_domain, opt_port, opt_path, opt_queryData, opt_fragment) {
<a name="line91"></a>  var out = &#39;&#39;;
<a name="line92"></a>
<a name="line93"></a>  if (opt_scheme) {
<a name="line94"></a>    out += opt_scheme + &#39;:&#39;;
<a name="line95"></a>  }
<a name="line96"></a>
<a name="line97"></a>  if (opt_domain) {
<a name="line98"></a>    out += &#39;//&#39;;
<a name="line99"></a>
<a name="line100"></a>    if (opt_userInfo) {
<a name="line101"></a>      out += opt_userInfo + &#39;@&#39;;
<a name="line102"></a>    }
<a name="line103"></a>
<a name="line104"></a>    out += opt_domain;
<a name="line105"></a>
<a name="line106"></a>    if (opt_port) {
<a name="line107"></a>      out += &#39;:&#39; + opt_port;
<a name="line108"></a>    }
<a name="line109"></a>  }
<a name="line110"></a>
<a name="line111"></a>  if (opt_path) {
<a name="line112"></a>    out += opt_path;
<a name="line113"></a>  }
<a name="line114"></a>
<a name="line115"></a>  if (opt_queryData) {
<a name="line116"></a>    out += &#39;?&#39; + opt_queryData;
<a name="line117"></a>  }
<a name="line118"></a>
<a name="line119"></a>  if (opt_fragment) {
<a name="line120"></a>    out += &#39;#&#39; + opt_fragment;
<a name="line121"></a>  }
<a name="line122"></a>
<a name="line123"></a>  return out;
<a name="line124"></a>};
<a name="line125"></a>
<a name="line126"></a>
<a name="line127"></a>/**
<a name="line128"></a> * A regular expression for breaking a URI into its component parts.
<a name="line129"></a> *
<a name="line130"></a> * {@link http://www.gbiv.com/protocols/uri/rfc/rfc3986.html#RFC2234} says
<a name="line131"></a> * As the &quot;first-match-wins&quot; algorithm is identical to the &quot;greedy&quot;
<a name="line132"></a> * disambiguation method used by POSIX regular expressions, it is natural and
<a name="line133"></a> * commonplace to use a regular expression for parsing the potential five
<a name="line134"></a> * components of a URI reference.
<a name="line135"></a> *
<a name="line136"></a> * The following line is the regular expression for breaking-down a
<a name="line137"></a> * well-formed URI reference into its components.
<a name="line138"></a> *
<a name="line139"></a> * &lt;pre&gt;
<a name="line140"></a> * ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
<a name="line141"></a> *  12            3  4          5       6  7        8 9
<a name="line142"></a> * &lt;/pre&gt;
<a name="line143"></a> *
<a name="line144"></a> * The numbers in the second line above are only to assist readability; they
<a name="line145"></a> * indicate the reference points for each subexpression (i.e., each paired
<a name="line146"></a> * parenthesis). We refer to the value matched for subexpression &lt;n&gt; as $&lt;n&gt;.
<a name="line147"></a> * For example, matching the above expression to
<a name="line148"></a> * &lt;pre&gt;
<a name="line149"></a> *     http://www.ics.uci.edu/pub/ietf/uri/#Related
<a name="line150"></a> * &lt;/pre&gt;
<a name="line151"></a> * results in the following subexpression matches:
<a name="line152"></a> * &lt;pre&gt;
<a name="line153"></a> *    $1 = http:
<a name="line154"></a> *    $2 = http
<a name="line155"></a> *    $3 = //www.ics.uci.edu
<a name="line156"></a> *    $4 = www.ics.uci.edu
<a name="line157"></a> *    $5 = /pub/ietf/uri/
<a name="line158"></a> *    $6 = &lt;undefined&gt;
<a name="line159"></a> *    $7 = &lt;undefined&gt;
<a name="line160"></a> *    $8 = #Related
<a name="line161"></a> *    $9 = Related
<a name="line162"></a> * &lt;/pre&gt;
<a name="line163"></a> * where &lt;undefined&gt; indicates that the component is not present, as is the
<a name="line164"></a> * case for the query component in the above example. Therefore, we can
<a name="line165"></a> * determine the value of the five components as
<a name="line166"></a> * &lt;pre&gt;
<a name="line167"></a> *    scheme    = $2
<a name="line168"></a> *    authority = $4
<a name="line169"></a> *    path      = $5
<a name="line170"></a> *    query     = $7
<a name="line171"></a> *    fragment  = $9
<a name="line172"></a> * &lt;/pre&gt;
<a name="line173"></a> *
<a name="line174"></a> * The regular expression has been modified slightly to expose the
<a name="line175"></a> * userInfo, domain, and port separately from the authority.
<a name="line176"></a> * The modified version yields
<a name="line177"></a> * &lt;pre&gt;
<a name="line178"></a> *    $1 = http              scheme
<a name="line179"></a> *    $2 = &lt;undefined&gt;       userInfo -\
<a name="line180"></a> *    $3 = www.ics.uci.edu   domain     | authority
<a name="line181"></a> *    $4 = &lt;undefined&gt;       port     -/
<a name="line182"></a> *    $5 = /pub/ietf/uri/    path
<a name="line183"></a> *    $6 = &lt;undefined&gt;       query without ?
<a name="line184"></a> *    $7 = Related           fragment without #
<a name="line185"></a> * &lt;/pre&gt;
<a name="line186"></a> * @type {!RegExp}
<a name="line187"></a> * @private
<a name="line188"></a> */
<a name="line189"></a>goog.uri.utils.splitRe_ = new RegExp(
<a name="line190"></a>    &#39;^&#39; +
<a name="line191"></a>    &#39;(?:&#39; +
<a name="line192"></a>      &#39;([^:/?#.]+)&#39; +                     // scheme - ignore special characters
<a name="line193"></a>                                          // used by other URL parts such as :,
<a name="line194"></a>                                          // ?, /, #, and .
<a name="line195"></a>    &#39;:)?&#39; +
<a name="line196"></a>    &#39;(?://&#39; +
<a name="line197"></a>      &#39;(?:([^/?#]*)@)?&#39; +                 // userInfo
<a name="line198"></a>      &#39;([^/#?]*?)&#39; +                      // domain
<a name="line199"></a>      &#39;(?::([0-9]+))?&#39; +                  // port
<a name="line200"></a>      &#39;(?=[/#?]|$)&#39; +                     // authority-terminating character
<a name="line201"></a>    &#39;)?&#39; +
<a name="line202"></a>    &#39;([^?#]+)?&#39; +                         // path
<a name="line203"></a>    &#39;(?:\\?([^#]*))?&#39; +                   // query
<a name="line204"></a>    &#39;(?:#(.*))?&#39; +                        // fragment
<a name="line205"></a>    &#39;$&#39;);
<a name="line206"></a>
<a name="line207"></a>
<a name="line208"></a>/**
<a name="line209"></a> * The index of each URI component in the return value of goog.uri.utils.split.
<a name="line210"></a> * @enum {number}
<a name="line211"></a> */
<a name="line212"></a>goog.uri.utils.ComponentIndex = {
<a name="line213"></a>  SCHEME: 1,
<a name="line214"></a>  USER_INFO: 2,
<a name="line215"></a>  DOMAIN: 3,
<a name="line216"></a>  PORT: 4,
<a name="line217"></a>  PATH: 5,
<a name="line218"></a>  QUERY_DATA: 6,
<a name="line219"></a>  FRAGMENT: 7
<a name="line220"></a>};
<a name="line221"></a>
<a name="line222"></a>
<a name="line223"></a>/**
<a name="line224"></a> * Splits a URI into its component parts.
<a name="line225"></a> *
<a name="line226"></a> * Each component can be accessed via the component indices; for example:
<a name="line227"></a> * &lt;pre&gt;
<a name="line228"></a> * goog.uri.utils.split(someStr)[goog.uri.utils.CompontentIndex.QUERY_DATA];
<a name="line229"></a> * &lt;/pre&gt;
<a name="line230"></a> *
<a name="line231"></a> * @param {string} uri The URI string to examine.
<a name="line232"></a> * @return {!Array.&lt;string|undefined&gt;} Each component still URI-encoded.
<a name="line233"></a> *     Each component that is present will contain the encoded value, whereas
<a name="line234"></a> *     components that are not present will be undefined or empty, depending
<a name="line235"></a> *     on the browser&#39;s regular expression implementation.  Never null, since
<a name="line236"></a> *     arbitrary strings may still look like path names.
<a name="line237"></a> */
<a name="line238"></a>goog.uri.utils.split = function(uri) {
<a name="line239"></a>
<a name="line240"></a>  // See @return comment -- never null.
<a name="line241"></a>  return /** @type {!Array.&lt;string|undefined&gt;} */ (
<a name="line242"></a>      uri.match(goog.uri.utils.splitRe_));
<a name="line243"></a>};
<a name="line244"></a>
<a name="line245"></a>
<a name="line246"></a>
<a name="line247"></a>
<a name="line248"></a>/**
<a name="line249"></a> * @param {?string} uri A possibly null string.
<a name="line250"></a> * @return {?string} The string URI-decoded, or null if uri is null.
<a name="line251"></a> * @private
<a name="line252"></a> */
<a name="line253"></a>goog.uri.utils.decodeIfPossible_ = function(uri) {
<a name="line254"></a>  return uri &amp;&amp; decodeURIComponent(uri);
<a name="line255"></a>};
<a name="line256"></a>
<a name="line257"></a>
<a name="line258"></a>/**
<a name="line259"></a> * Gets a URI component by index.
<a name="line260"></a> *
<a name="line261"></a> * It is preferred to use the getPathEncoded() variety of functions ahead,
<a name="line262"></a> * since they are more readable.
<a name="line263"></a> *
<a name="line264"></a> * @param {goog.uri.utils.ComponentIndex} componentIndex The component index.
<a name="line265"></a> * @param {string} uri The URI to examine.
<a name="line266"></a> * @return {?string} The still-encoded component, or null if the component
<a name="line267"></a> *     is not present.
<a name="line268"></a> * @private
<a name="line269"></a> */
<a name="line270"></a>goog.uri.utils.getComponentByIndex_ = function(componentIndex, uri) {
<a name="line271"></a>  // Convert undefined, null, and empty string into null.
<a name="line272"></a>  return goog.uri.utils.split(uri)[componentIndex] || null;
<a name="line273"></a>};
<a name="line274"></a>
<a name="line275"></a>
<a name="line276"></a>/**
<a name="line277"></a> * @param {string} uri The URI to examine.
<a name="line278"></a> * @return {?string} The protocol or scheme, or null if none.  Does not
<a name="line279"></a> *     include trailing colons or slashes.
<a name="line280"></a> */
<a name="line281"></a>goog.uri.utils.getScheme = function(uri) {
<a name="line282"></a>  return goog.uri.utils.getComponentByIndex_(
<a name="line283"></a>      goog.uri.utils.ComponentIndex.SCHEME, uri);
<a name="line284"></a>};
<a name="line285"></a>
<a name="line286"></a>
<a name="line287"></a>/**
<a name="line288"></a> * Gets the effective scheme for the URL.  If the URL is relative then the
<a name="line289"></a> * scheme is derived from the page&#39;s location.
<a name="line290"></a> * @param {string} uri The URI to examine.
<a name="line291"></a> * @return {string} The protocol or scheme, always lower case.
<a name="line292"></a> */
<a name="line293"></a>goog.uri.utils.getEffectiveScheme = function(uri) {
<a name="line294"></a>  var scheme = goog.uri.utils.getScheme(uri);
<a name="line295"></a>  if (!scheme &amp;&amp; self.location) {
<a name="line296"></a>    var protocol = self.location.protocol;
<a name="line297"></a>    scheme = protocol.substr(0, protocol.length - 1);
<a name="line298"></a>  }
<a name="line299"></a>  // NOTE: When called from a web worker in Firefox 3.5, location maybe null.
<a name="line300"></a>  // All other browsers with web workers support self.location from the worker.
<a name="line301"></a>  return scheme ? scheme.toLowerCase() : &#39;&#39;;
<a name="line302"></a>};
<a name="line303"></a>
<a name="line304"></a>
<a name="line305"></a>/**
<a name="line306"></a> * @param {string} uri The URI to examine.
<a name="line307"></a> * @return {?string} The user name still encoded, or null if none.
<a name="line308"></a> */
<a name="line309"></a>goog.uri.utils.getUserInfoEncoded = function(uri) {
<a name="line310"></a>  return goog.uri.utils.getComponentByIndex_(
<a name="line311"></a>      goog.uri.utils.ComponentIndex.USER_INFO, uri);
<a name="line312"></a>};
<a name="line313"></a>
<a name="line314"></a>
<a name="line315"></a>/**
<a name="line316"></a> * @param {string} uri The URI to examine.
<a name="line317"></a> * @return {?string} The decoded user info, or null if none.
<a name="line318"></a> */
<a name="line319"></a>goog.uri.utils.getUserInfo = function(uri) {
<a name="line320"></a>  return goog.uri.utils.decodeIfPossible_(
<a name="line321"></a>      goog.uri.utils.getUserInfoEncoded(uri));
<a name="line322"></a>};
<a name="line323"></a>
<a name="line324"></a>
<a name="line325"></a>/**
<a name="line326"></a> * @param {string} uri The URI to examine.
<a name="line327"></a> * @return {?string} The domain name still encoded, or null if none.
<a name="line328"></a> */
<a name="line329"></a>goog.uri.utils.getDomainEncoded = function(uri) {
<a name="line330"></a>  return goog.uri.utils.getComponentByIndex_(
<a name="line331"></a>      goog.uri.utils.ComponentIndex.DOMAIN, uri);
<a name="line332"></a>};
<a name="line333"></a>
<a name="line334"></a>
<a name="line335"></a>/**
<a name="line336"></a> * @param {string} uri The URI to examine.
<a name="line337"></a> * @return {?string} The decoded domain, or null if none.
<a name="line338"></a> */
<a name="line339"></a>goog.uri.utils.getDomain = function(uri) {
<a name="line340"></a>  return goog.uri.utils.decodeIfPossible_(goog.uri.utils.getDomainEncoded(uri));
<a name="line341"></a>};
<a name="line342"></a>
<a name="line343"></a>
<a name="line344"></a>/**
<a name="line345"></a> * @param {string} uri The URI to examine.
<a name="line346"></a> * @return {?number} The port number, or null if none.
<a name="line347"></a> */
<a name="line348"></a>goog.uri.utils.getPort = function(uri) {
<a name="line349"></a>  // Coerce to a number.  If the result of getComponentByIndex_ is null or
<a name="line350"></a>  // non-numeric, the number coersion yields NaN.  This will then return
<a name="line351"></a>  // null for all non-numeric cases (though also zero, which isn&#39;t a relevant
<a name="line352"></a>  // port number).
<a name="line353"></a>  return Number(goog.uri.utils.getComponentByIndex_(
<a name="line354"></a>      goog.uri.utils.ComponentIndex.PORT, uri)) || null;
<a name="line355"></a>};
<a name="line356"></a>
<a name="line357"></a>
<a name="line358"></a>/**
<a name="line359"></a> * @param {string} uri The URI to examine.
<a name="line360"></a> * @return {?string} The path still encoded, or null if none. Includes the
<a name="line361"></a> *     leading slash, if any.
<a name="line362"></a> */
<a name="line363"></a>goog.uri.utils.getPathEncoded = function(uri) {
<a name="line364"></a>  return goog.uri.utils.getComponentByIndex_(
<a name="line365"></a>      goog.uri.utils.ComponentIndex.PATH, uri);
<a name="line366"></a>};
<a name="line367"></a>
<a name="line368"></a>
<a name="line369"></a>/**
<a name="line370"></a> * @param {string} uri The URI to examine.
<a name="line371"></a> * @return {?string} The decoded path, or null if none.  Includes the leading
<a name="line372"></a> *     slash, if any.
<a name="line373"></a> */
<a name="line374"></a>goog.uri.utils.getPath = function(uri) {
<a name="line375"></a>  return goog.uri.utils.decodeIfPossible_(goog.uri.utils.getPathEncoded(uri));
<a name="line376"></a>};
<a name="line377"></a>
<a name="line378"></a>
<a name="line379"></a>/**
<a name="line380"></a> * @param {string} uri The URI to examine.
<a name="line381"></a> * @return {?string} The query data still encoded, or null if none.  Does not
<a name="line382"></a> *     include the question mark itself.
<a name="line383"></a> */
<a name="line384"></a>goog.uri.utils.getQueryData = function(uri) {
<a name="line385"></a>  return goog.uri.utils.getComponentByIndex_(
<a name="line386"></a>      goog.uri.utils.ComponentIndex.QUERY_DATA, uri);
<a name="line387"></a>};
<a name="line388"></a>
<a name="line389"></a>
<a name="line390"></a>/**
<a name="line391"></a> * @param {string} uri The URI to examine.
<a name="line392"></a> * @return {?string} The fragment identifier, or null if none.  Does not
<a name="line393"></a> *     include the hash mark itself.
<a name="line394"></a> */
<a name="line395"></a>goog.uri.utils.getFragmentEncoded = function(uri) {
<a name="line396"></a>  // The hash mark may not appear in any other part of the URL.
<a name="line397"></a>  var hashIndex = uri.indexOf(&#39;#&#39;);
<a name="line398"></a>  return hashIndex &lt; 0 ? null : uri.substr(hashIndex + 1);
<a name="line399"></a>};
<a name="line400"></a>
<a name="line401"></a>
<a name="line402"></a>/**
<a name="line403"></a> * @param {string} uri The URI to examine.
<a name="line404"></a> * @param {?string} fragment The encoded fragment identifier, or null if none.
<a name="line405"></a> *     Does not include the hash mark itself.
<a name="line406"></a> * @return {string} The URI with the fragment set.
<a name="line407"></a> */
<a name="line408"></a>goog.uri.utils.setFragmentEncoded = function(uri, fragment) {
<a name="line409"></a>  return goog.uri.utils.removeFragment(uri) + (fragment ? &#39;#&#39; + fragment : &#39;&#39;);
<a name="line410"></a>};
<a name="line411"></a>
<a name="line412"></a>
<a name="line413"></a>/**
<a name="line414"></a> * @param {string} uri The URI to examine.
<a name="line415"></a> * @return {?string} The decoded fragment identifier, or null if none.  Does
<a name="line416"></a> *     not include the hash mark.
<a name="line417"></a> */
<a name="line418"></a>goog.uri.utils.getFragment = function(uri) {
<a name="line419"></a>  return goog.uri.utils.decodeIfPossible_(
<a name="line420"></a>      goog.uri.utils.getFragmentEncoded(uri));
<a name="line421"></a>};
<a name="line422"></a>
<a name="line423"></a>
<a name="line424"></a>/**
<a name="line425"></a> * Extracts everything up to the port of the URI.
<a name="line426"></a> * @param {string} uri The URI string.
<a name="line427"></a> * @return {string} Everything up to and including the port.
<a name="line428"></a> */
<a name="line429"></a>goog.uri.utils.getHost = function(uri) {
<a name="line430"></a>  var pieces = goog.uri.utils.split(uri);
<a name="line431"></a>  return goog.uri.utils.buildFromEncodedParts(
<a name="line432"></a>      pieces[goog.uri.utils.ComponentIndex.SCHEME],
<a name="line433"></a>      pieces[goog.uri.utils.ComponentIndex.USER_INFO],
<a name="line434"></a>      pieces[goog.uri.utils.ComponentIndex.DOMAIN],
<a name="line435"></a>      pieces[goog.uri.utils.ComponentIndex.PORT]);
<a name="line436"></a>};
<a name="line437"></a>
<a name="line438"></a>
<a name="line439"></a>/**
<a name="line440"></a> * Extracts the path of the URL and everything after.
<a name="line441"></a> * @param {string} uri The URI string.
<a name="line442"></a> * @return {string} The URI, starting at the path and including the query
<a name="line443"></a> *     parameters and fragment identifier.
<a name="line444"></a> */
<a name="line445"></a>goog.uri.utils.getPathAndAfter = function(uri) {
<a name="line446"></a>  var pieces = goog.uri.utils.split(uri);
<a name="line447"></a>  return goog.uri.utils.buildFromEncodedParts(null, null, null, null,
<a name="line448"></a>      pieces[goog.uri.utils.ComponentIndex.PATH],
<a name="line449"></a>      pieces[goog.uri.utils.ComponentIndex.QUERY_DATA],
<a name="line450"></a>      pieces[goog.uri.utils.ComponentIndex.FRAGMENT]);
<a name="line451"></a>};
<a name="line452"></a>
<a name="line453"></a>
<a name="line454"></a>/**
<a name="line455"></a> * Gets the URI with the fragment identifier removed.
<a name="line456"></a> * @param {string} uri The URI to examine.
<a name="line457"></a> * @return {string} Everything preceding the hash mark.
<a name="line458"></a> */
<a name="line459"></a>goog.uri.utils.removeFragment = function(uri) {
<a name="line460"></a>  // The hash mark may not appear in any other part of the URL.
<a name="line461"></a>  var hashIndex = uri.indexOf(&#39;#&#39;);
<a name="line462"></a>  return hashIndex &lt; 0 ? uri : uri.substr(0, hashIndex);
<a name="line463"></a>};
<a name="line464"></a>
<a name="line465"></a>
<a name="line466"></a>/**
<a name="line467"></a> * Ensures that two URI&#39;s have the exact same domain, scheme, and port.
<a name="line468"></a> *
<a name="line469"></a> * Unlike the version in goog.Uri, this checks protocol, and therefore is
<a name="line470"></a> * suitable for checking against the browser&#39;s same-origin policy.
<a name="line471"></a> *
<a name="line472"></a> * @param {string} uri1 The first URI.
<a name="line473"></a> * @param {string} uri2 The second URI.
<a name="line474"></a> * @return {boolean} Whether they have the same domain and port.
<a name="line475"></a> */
<a name="line476"></a>goog.uri.utils.haveSameDomain = function(uri1, uri2) {
<a name="line477"></a>  var pieces1 = goog.uri.utils.split(uri1);
<a name="line478"></a>  var pieces2 = goog.uri.utils.split(uri2);
<a name="line479"></a>  return pieces1[goog.uri.utils.ComponentIndex.DOMAIN] ==
<a name="line480"></a>             pieces2[goog.uri.utils.ComponentIndex.DOMAIN] &amp;&amp;
<a name="line481"></a>         pieces1[goog.uri.utils.ComponentIndex.SCHEME] ==
<a name="line482"></a>             pieces2[goog.uri.utils.ComponentIndex.SCHEME] &amp;&amp;
<a name="line483"></a>         pieces1[goog.uri.utils.ComponentIndex.PORT] ==
<a name="line484"></a>             pieces2[goog.uri.utils.ComponentIndex.PORT];
<a name="line485"></a>};
<a name="line486"></a>
<a name="line487"></a>
<a name="line488"></a>/**
<a name="line489"></a> * Asserts that there are no fragment or query identifiers, only in uncompiled
<a name="line490"></a> * mode.
<a name="line491"></a> * @param {string} uri The URI to examine.
<a name="line492"></a> * @private
<a name="line493"></a> */
<a name="line494"></a>goog.uri.utils.assertNoFragmentsOrQueries_ = function(uri) {
<a name="line495"></a>  // NOTE: would use goog.asserts here, but jscompiler doesn&#39;t know that
<a name="line496"></a>  // indexOf has no side effects.
<a name="line497"></a>  if (goog.DEBUG &amp;&amp; (uri.indexOf(&#39;#&#39;) &gt;= 0 || uri.indexOf(&#39;?&#39;) &gt;= 0)) {
<a name="line498"></a>    throw Error(&#39;goog.uri.utils: Fragment or query identifiers are not &#39; +
<a name="line499"></a>        &#39;supported: [&#39; + uri + &#39;]&#39;);
<a name="line500"></a>  }
<a name="line501"></a>};
<a name="line502"></a>
<a name="line503"></a>
<a name="line504"></a>/**
<a name="line505"></a> * Supported query parameter values by the parameter serializing utilities.
<a name="line506"></a> *
<a name="line507"></a> * If a value is null or undefined, the key-value pair is skipped, as an easy
<a name="line508"></a> * way to omit parameters conditionally.  Non-array parameters are converted
<a name="line509"></a> * to a string and URI encoded.  Array values are expanded into multiple
<a name="line510"></a> * &amp;key=value pairs, with each element stringized and URI-encoded.
<a name="line511"></a> *
<a name="line512"></a> * @typedef {*}
<a name="line513"></a> */
<a name="line514"></a>goog.uri.utils.QueryValue;
<a name="line515"></a>
<a name="line516"></a>
<a name="line517"></a>/**
<a name="line518"></a> * An array representing a set of query parameters with alternating keys
<a name="line519"></a> * and values.
<a name="line520"></a> *
<a name="line521"></a> * Keys are assumed to be URI encoded already and live at even indices.  See
<a name="line522"></a> * goog.uri.utils.QueryValue for details on how parameter values are encoded.
<a name="line523"></a> *
<a name="line524"></a> * Example:
<a name="line525"></a> * &lt;pre&gt;
<a name="line526"></a> * var data = [
<a name="line527"></a> *   // Simple param: ?name=BobBarker
<a name="line528"></a> *   &#39;name&#39;, &#39;BobBarker&#39;,
<a name="line529"></a> *   // Conditional param -- may be omitted entirely.
<a name="line530"></a> *   &#39;specialDietaryNeeds&#39;, hasDietaryNeeds() ? getDietaryNeeds() : null,
<a name="line531"></a> *   // Multi-valued param: &amp;house=LosAngeles&amp;house=NewYork&amp;house=null
<a name="line532"></a> *   &#39;house&#39;, [&#39;LosAngeles&#39;, &#39;NewYork&#39;, null]
<a name="line533"></a> * ];
<a name="line534"></a> * &lt;/pre&gt;
<a name="line535"></a> *
<a name="line536"></a> * @typedef {!Array.&lt;string|goog.uri.utils.QueryValue&gt;}
<a name="line537"></a> */
<a name="line538"></a>goog.uri.utils.QueryArray;
<a name="line539"></a>
<a name="line540"></a>
<a name="line541"></a>/**
<a name="line542"></a> * Appends a URI and query data in a string buffer with special preconditions.
<a name="line543"></a> *
<a name="line544"></a> * Internal implementation utility, performing very few object allocations.
<a name="line545"></a> *
<a name="line546"></a> * @param {!Array.&lt;string|undefined&gt;} buffer A string buffer.  The first element
<a name="line547"></a> *     must be the base URI, and may have a fragment identifier.  If the array
<a name="line548"></a> *     contains more than one element, the second element must be an ampersand,
<a name="line549"></a> *     and may be overwritten, depending on the base URI.  Undefined elements
<a name="line550"></a> *     are treated as empty-string.
<a name="line551"></a> * @return {string} The concatenated URI and query data.
<a name="line552"></a> * @private
<a name="line553"></a> */
<a name="line554"></a>goog.uri.utils.appendQueryData_ = function(buffer) {
<a name="line555"></a>  if (buffer[1]) {
<a name="line556"></a>    // At least one query parameter was added.  We need to check the
<a name="line557"></a>    // punctuation mark, which is currently an ampersand, and also make sure
<a name="line558"></a>    // there aren&#39;t any interfering fragment identifiers.
<a name="line559"></a>    var baseUri = /** @type {string} */ (buffer[0]);
<a name="line560"></a>    var hashIndex = baseUri.indexOf(&#39;#&#39;);
<a name="line561"></a>    if (hashIndex &gt;= 0) {
<a name="line562"></a>      // Move the fragment off the base part of the URI into the end.
<a name="line563"></a>      buffer.push(baseUri.substr(hashIndex));
<a name="line564"></a>      buffer[0] = baseUri = baseUri.substr(0, hashIndex);
<a name="line565"></a>    }
<a name="line566"></a>    var questionIndex = baseUri.indexOf(&#39;?&#39;);
<a name="line567"></a>    if (questionIndex &lt; 0) {
<a name="line568"></a>      // No question mark, so we need a question mark instead of an ampersand.
<a name="line569"></a>      buffer[1] = &#39;?&#39;;
<a name="line570"></a>    } else if (questionIndex == baseUri.length - 1) {
<a name="line571"></a>      // Question mark is the very last character of the existing URI, so don&#39;t
<a name="line572"></a>      // append an additional delimiter.
<a name="line573"></a>      buffer[1] = undefined;
<a name="line574"></a>    }
<a name="line575"></a>  }
<a name="line576"></a>
<a name="line577"></a>  return buffer.join(&#39;&#39;);
<a name="line578"></a>};
<a name="line579"></a>
<a name="line580"></a>
<a name="line581"></a>/**
<a name="line582"></a> * Appends key=value pairs to an array, supporting multi-valued objects.
<a name="line583"></a> * @param {string} key The key prefix.
<a name="line584"></a> * @param {goog.uri.utils.QueryValue} value The value to serialize.
<a name="line585"></a> * @param {!Array.&lt;string&gt;} pairs The array to which the &#39;key=value&#39; strings
<a name="line586"></a> *     should be appended.
<a name="line587"></a> * @private
<a name="line588"></a> */
<a name="line589"></a>goog.uri.utils.appendKeyValuePairs_ = function(key, value, pairs) {
<a name="line590"></a>  if (goog.isArray(value)) {
<a name="line591"></a>    // Convince the compiler it&#39;s an array.
<a name="line592"></a>    goog.asserts.assertArray(value);
<a name="line593"></a>    for (var j = 0; j &lt; value.length; j++) {
<a name="line594"></a>      // Convert to string explicitly, to short circuit the null and array
<a name="line595"></a>      // logic in this function -- this ensures that null and undefined get
<a name="line596"></a>      // written as literal &#39;null&#39; and &#39;undefined&#39;, and arrays don&#39;t get
<a name="line597"></a>      // expanded out but instead encoded in the default way.
<a name="line598"></a>      goog.uri.utils.appendKeyValuePairs_(key, String(value[j]), pairs);
<a name="line599"></a>    }
<a name="line600"></a>  } else if (value != null) {
<a name="line601"></a>    // Skip a top-level null or undefined entirely.
<a name="line602"></a>    pairs.push(&#39;&amp;&#39;, key,
<a name="line603"></a>        // Check for empty string. Zero gets encoded into the url as literal
<a name="line604"></a>        // strings.  For empty string, skip the equal sign, to be consistent
<a name="line605"></a>        // with UriBuilder.java.
<a name="line606"></a>        value === &#39;&#39; ? &#39;&#39; : &#39;=&#39;,
<a name="line607"></a>        goog.string.urlEncode(value));
<a name="line608"></a>  }
<a name="line609"></a>};
<a name="line610"></a>
<a name="line611"></a>
<a name="line612"></a>/**
<a name="line613"></a> * Builds a buffer of query data from a sequence of alternating keys and values.
<a name="line614"></a> *
<a name="line615"></a> * @param {!Array.&lt;string|undefined&gt;} buffer A string buffer to append to.  The
<a name="line616"></a> *     first element appended will be an &#39;&amp;&#39;, and may be replaced by the caller.
<a name="line617"></a> * @param {goog.uri.utils.QueryArray|Arguments} keysAndValues An array with
<a name="line618"></a> *     alternating keys and values -- see the typedef.
<a name="line619"></a> * @param {number=} opt_startIndex A start offset into the arary, defaults to 0.
<a name="line620"></a> * @return {!Array.&lt;string|undefined&gt;} The buffer argument.
<a name="line621"></a> * @private
<a name="line622"></a> */
<a name="line623"></a>goog.uri.utils.buildQueryDataBuffer_ = function(
<a name="line624"></a>    buffer, keysAndValues, opt_startIndex) {
<a name="line625"></a>  goog.asserts.assert(Math.max(keysAndValues.length - (opt_startIndex || 0),
<a name="line626"></a>      0) % 2 == 0, &#39;goog.uri.utils: Key/value lists must be even in length.&#39;);
<a name="line627"></a>
<a name="line628"></a>  for (var i = opt_startIndex || 0; i &lt; keysAndValues.length; i += 2) {
<a name="line629"></a>    goog.uri.utils.appendKeyValuePairs_(
<a name="line630"></a>        keysAndValues[i], keysAndValues[i + 1], buffer);
<a name="line631"></a>  }
<a name="line632"></a>
<a name="line633"></a>  return buffer;
<a name="line634"></a>};
<a name="line635"></a>
<a name="line636"></a>
<a name="line637"></a>/**
<a name="line638"></a> * Builds a query data string from a sequence of alternating keys and values.
<a name="line639"></a> * Currently generates &quot;&amp;key&amp;&quot; for empty args.
<a name="line640"></a> *
<a name="line641"></a> * @param {goog.uri.utils.QueryArray} keysAndValues Alternating keys and
<a name="line642"></a> *     values.  See the typedef.
<a name="line643"></a> * @param {number=} opt_startIndex A start offset into the arary, defaults to 0.
<a name="line644"></a> * @return {string} The encoded query string, in the for &#39;a=1&amp;b=2&#39;.
<a name="line645"></a> */
<a name="line646"></a>goog.uri.utils.buildQueryData = function(keysAndValues, opt_startIndex) {
<a name="line647"></a>  var buffer = goog.uri.utils.buildQueryDataBuffer_(
<a name="line648"></a>      [], keysAndValues, opt_startIndex);
<a name="line649"></a>  buffer[0] = &#39;&#39;; // Remove the leading ampersand.
<a name="line650"></a>  return buffer.join(&#39;&#39;);
<a name="line651"></a>};
<a name="line652"></a>
<a name="line653"></a>
<a name="line654"></a>/**
<a name="line655"></a> * Builds a buffer of query data from a map.
<a name="line656"></a> *
<a name="line657"></a> * @param {!Array.&lt;string|undefined&gt;} buffer A string buffer to append to.  The
<a name="line658"></a> *     first element appended will be an &#39;&amp;&#39;, and may be replaced by the caller.
<a name="line659"></a> * @param {Object.&lt;goog.uri.utils.QueryValue&gt;} map An object where keys are
<a name="line660"></a> *     URI-encoded parameter keys, and the values conform to the contract
<a name="line661"></a> *     specified in the goog.uri.utils.QueryValue typedef.
<a name="line662"></a> * @return {!Array.&lt;string|undefined&gt;} The buffer argument.
<a name="line663"></a> * @private
<a name="line664"></a> */
<a name="line665"></a>goog.uri.utils.buildQueryDataBufferFromMap_ = function(buffer, map) {
<a name="line666"></a>  for (var key in map) {
<a name="line667"></a>    goog.uri.utils.appendKeyValuePairs_(key, map[key], buffer);
<a name="line668"></a>  }
<a name="line669"></a>
<a name="line670"></a>  return buffer;
<a name="line671"></a>};
<a name="line672"></a>
<a name="line673"></a>
<a name="line674"></a>/**
<a name="line675"></a> * Builds a query data string from a map.
<a name="line676"></a> * Currently generates &quot;&amp;key&amp;&quot; for empty args.
<a name="line677"></a> *
<a name="line678"></a> * @param {Object} map An object where keys are URI-encoded parameter keys,
<a name="line679"></a> *     and the values are arbitrary types or arrays.  Keys with a null value
<a name="line680"></a> *     are dropped.
<a name="line681"></a> * @return {string} The encoded query string, in the for &#39;a=1&amp;b=2&#39;.
<a name="line682"></a> */
<a name="line683"></a>goog.uri.utils.buildQueryDataFromMap = function(map) {
<a name="line684"></a>  var buffer = goog.uri.utils.buildQueryDataBufferFromMap_([], map);
<a name="line685"></a>  buffer[0] = &#39;&#39;;
<a name="line686"></a>  return buffer.join(&#39;&#39;);
<a name="line687"></a>};
<a name="line688"></a>
<a name="line689"></a>
<a name="line690"></a>/**
<a name="line691"></a> * Appends URI parameters to an existing URI.
<a name="line692"></a> *
<a name="line693"></a> * The variable arguments may contain alternating keys and values.  Keys are
<a name="line694"></a> * assumed to be already URI encoded.  The values should not be URI-encoded,
<a name="line695"></a> * and will instead be encoded by this function.
<a name="line696"></a> * &lt;pre&gt;
<a name="line697"></a> * appendParams(&#39;http://www.foo.com?existing=true&#39;,
<a name="line698"></a> *     &#39;key1&#39;, &#39;value1&#39;,
<a name="line699"></a> *     &#39;key2&#39;, &#39;value?willBeEncoded&#39;,
<a name="line700"></a> *     &#39;key3&#39;, [&#39;valueA&#39;, &#39;valueB&#39;, &#39;valueC&#39;],
<a name="line701"></a> *     &#39;key4&#39;, null);
<a name="line702"></a> * result: &#39;http://www.foo.com?existing=true&amp;&#39; +
<a name="line703"></a> *     &#39;key1=value1&amp;&#39; +
<a name="line704"></a> *     &#39;key2=value%3FwillBeEncoded&amp;&#39; +
<a name="line705"></a> *     &#39;key3=valueA&amp;key3=valueB&amp;key3=valueC&#39;
<a name="line706"></a> * &lt;/pre&gt;
<a name="line707"></a> *
<a name="line708"></a> * A single call to this function will not exhibit quadratic behavior in IE,
<a name="line709"></a> * whereas multiple repeated calls may, although the effect is limited by
<a name="line710"></a> * fact that URL&#39;s generally can&#39;t exceed 2kb.
<a name="line711"></a> *
<a name="line712"></a> * @param {string} uri The original URI, which may already have query data.
<a name="line713"></a> * @param {...(goog.uri.utils.QueryArray|string|goog.uri.utils.QueryValue)} var_args
<a name="line714"></a> *     An array or argument list conforming to goog.uri.utils.QueryArray.
<a name="line715"></a> * @return {string} The URI with all query parameters added.
<a name="line716"></a> */
<a name="line717"></a>goog.uri.utils.appendParams = function(uri, var_args) {
<a name="line718"></a>  return goog.uri.utils.appendQueryData_(
<a name="line719"></a>      arguments.length == 2 ?
<a name="line720"></a>      goog.uri.utils.buildQueryDataBuffer_([uri], arguments[1], 0) :
<a name="line721"></a>      goog.uri.utils.buildQueryDataBuffer_([uri], arguments, 1));
<a name="line722"></a>};
<a name="line723"></a>
<a name="line724"></a>
<a name="line725"></a>/**
<a name="line726"></a> * Appends query parameters from a map.
<a name="line727"></a> *
<a name="line728"></a> * @param {string} uri The original URI, which may already have query data.
<a name="line729"></a> * @param {Object} map An object where keys are URI-encoded parameter keys,
<a name="line730"></a> *     and the values are arbitrary types or arrays.  Keys with a null value
<a name="line731"></a> *     are dropped.
<a name="line732"></a> * @return {string} The new parameters.
<a name="line733"></a> */
<a name="line734"></a>goog.uri.utils.appendParamsFromMap = function(uri, map) {
<a name="line735"></a>  return goog.uri.utils.appendQueryData_(
<a name="line736"></a>      goog.uri.utils.buildQueryDataBufferFromMap_([uri], map));
<a name="line737"></a>};
<a name="line738"></a>
<a name="line739"></a>
<a name="line740"></a>/**
<a name="line741"></a> * Appends a single URI parameter.
<a name="line742"></a> *
<a name="line743"></a> * Repeated calls to this can exhibit quadratic behavior in IE6 due to the
<a name="line744"></a> * way string append works, though it should be limited given the 2kb limit.
<a name="line745"></a> *
<a name="line746"></a> * @param {string} uri The original URI, which may already have query data.
<a name="line747"></a> * @param {string} key The key, which must already be URI encoded.
<a name="line748"></a> * @param {*} value The value, which will be stringized and encoded (assumed
<a name="line749"></a> *     not already to be encoded).
<a name="line750"></a> * @return {string} The URI with the query parameter added.
<a name="line751"></a> */
<a name="line752"></a>goog.uri.utils.appendParam = function(uri, key, value) {
<a name="line753"></a>  return goog.uri.utils.appendQueryData_(
<a name="line754"></a>      [uri, &#39;&amp;&#39;, key, &#39;=&#39;, goog.string.urlEncode(value)]);
<a name="line755"></a>};
<a name="line756"></a>
<a name="line757"></a>
<a name="line758"></a>/**
<a name="line759"></a> * Finds the next instance of a query parameter with the specified name.
<a name="line760"></a> *
<a name="line761"></a> * Does not instantiate any objects.
<a name="line762"></a> *
<a name="line763"></a> * @param {string} uri The URI to search.  May contain a fragment identifier
<a name="line764"></a> *     if opt_hashIndex is specified.
<a name="line765"></a> * @param {number} startIndex The index to begin searching for the key at.  A
<a name="line766"></a> *     match may be found even if this is one character after the ampersand.
<a name="line767"></a> * @param {string} keyEncoded The URI-encoded key.
<a name="line768"></a> * @param {number} hashOrEndIndex Index to stop looking at.  If a hash
<a name="line769"></a> *     mark is present, it should be its index, otherwise it should be the
<a name="line770"></a> *     length of the string.
<a name="line771"></a> * @return {number} The position of the first character in the key&#39;s name,
<a name="line772"></a> *     immediately after either a question mark or a dot.
<a name="line773"></a> * @private
<a name="line774"></a> */
<a name="line775"></a>goog.uri.utils.findParam_ = function(
<a name="line776"></a>    uri, startIndex, keyEncoded, hashOrEndIndex) {
<a name="line777"></a>  var index = startIndex;
<a name="line778"></a>  var keyLength = keyEncoded.length;
<a name="line779"></a>
<a name="line780"></a>  // Search for the key itself and post-filter for surronuding punctuation,
<a name="line781"></a>  // rather than expensively building a regexp.
<a name="line782"></a>  while ((index = uri.indexOf(keyEncoded, index)) &gt;= 0 &amp;&amp;
<a name="line783"></a>      index &lt; hashOrEndIndex) {
<a name="line784"></a>    var precedingChar = uri.charCodeAt(index - 1);
<a name="line785"></a>    // Ensure that the preceding character is &#39;&amp;&#39; or &#39;?&#39;.
<a name="line786"></a>    if (precedingChar == goog.uri.utils.CharCode_.AMPERSAND ||
<a name="line787"></a>        precedingChar == goog.uri.utils.CharCode_.QUESTION) {
<a name="line788"></a>      // Ensure the following character is &#39;&amp;&#39;, &#39;=&#39;, &#39;#&#39;, or NaN
<a name="line789"></a>      // (end of string).
<a name="line790"></a>      var followingChar = uri.charCodeAt(index + keyLength);
<a name="line791"></a>      if (!followingChar ||
<a name="line792"></a>          followingChar == goog.uri.utils.CharCode_.EQUAL ||
<a name="line793"></a>          followingChar == goog.uri.utils.CharCode_.AMPERSAND ||
<a name="line794"></a>          followingChar == goog.uri.utils.CharCode_.HASH) {
<a name="line795"></a>        return index;
<a name="line796"></a>      }
<a name="line797"></a>    }
<a name="line798"></a>    index += keyLength + 1;
<a name="line799"></a>  }
<a name="line800"></a>
<a name="line801"></a>  return -1;
<a name="line802"></a>};
<a name="line803"></a>
<a name="line804"></a>
<a name="line805"></a>/**
<a name="line806"></a> * Regular expression for finding a hash mark or end of string.
<a name="line807"></a> * @type {RegExp}
<a name="line808"></a> * @private
<a name="line809"></a> */
<a name="line810"></a>goog.uri.utils.hashOrEndRe_ = /#|$/;
<a name="line811"></a>
<a name="line812"></a>
<a name="line813"></a>/**
<a name="line814"></a> * Determines if the URI contains a specific key.
<a name="line815"></a> *
<a name="line816"></a> * Performs no object instantiations.
<a name="line817"></a> *
<a name="line818"></a> * @param {string} uri The URI to process.  May contain a fragment
<a name="line819"></a> *     identifier.
<a name="line820"></a> * @param {string} keyEncoded The URI-encoded key.  Case-sensitive.
<a name="line821"></a> * @return {boolean} Whether the key is present.
<a name="line822"></a> */
<a name="line823"></a>goog.uri.utils.hasParam = function(uri, keyEncoded) {
<a name="line824"></a>  return goog.uri.utils.findParam_(uri, 0, keyEncoded,
<a name="line825"></a>      uri.search(goog.uri.utils.hashOrEndRe_)) &gt;= 0;
<a name="line826"></a>};
<a name="line827"></a>
<a name="line828"></a>
<a name="line829"></a>/**
<a name="line830"></a> * Gets the first value of a query parameter.
<a name="line831"></a> * @param {string} uri The URI to process.  May contain a fragment.
<a name="line832"></a> * @param {string} keyEncoded The URI-encoded key.  Case-sensitive.
<a name="line833"></a> * @return {?string} The first value of the parameter (URI-decoded), or null
<a name="line834"></a> *     if the parameter is not found.
<a name="line835"></a> */
<a name="line836"></a>goog.uri.utils.getParamValue = function(uri, keyEncoded) {
<a name="line837"></a>  var hashOrEndIndex = uri.search(goog.uri.utils.hashOrEndRe_);
<a name="line838"></a>  var foundIndex = goog.uri.utils.findParam_(
<a name="line839"></a>      uri, 0, keyEncoded, hashOrEndIndex);
<a name="line840"></a>
<a name="line841"></a>  if (foundIndex &lt; 0) {
<a name="line842"></a>    return null;
<a name="line843"></a>  } else {
<a name="line844"></a>    var endPosition = uri.indexOf(&#39;&amp;&#39;, foundIndex);
<a name="line845"></a>    if (endPosition &lt; 0 || endPosition &gt; hashOrEndIndex) {
<a name="line846"></a>      endPosition = hashOrEndIndex;
<a name="line847"></a>    }
<a name="line848"></a>    // Progress forth to the end of the &quot;key=&quot; or &quot;key&amp;&quot; substring.
<a name="line849"></a>    foundIndex += keyEncoded.length + 1;
<a name="line850"></a>    // Use substr, because it (unlike substring) will return empty string
<a name="line851"></a>    // if foundIndex &gt; endPosition.
<a name="line852"></a>    return goog.string.urlDecode(
<a name="line853"></a>        uri.substr(foundIndex, endPosition - foundIndex));
<a name="line854"></a>  }
<a name="line855"></a>};
<a name="line856"></a>
<a name="line857"></a>
<a name="line858"></a>/**
<a name="line859"></a> * Gets all values of a query parameter.
<a name="line860"></a> * @param {string} uri The URI to process.  May contain a framgnet.
<a name="line861"></a> * @param {string} keyEncoded The URI-encoded key.  Case-snsitive.
<a name="line862"></a> * @return {!Array.&lt;string&gt;} All URI-decoded values with the given key.
<a name="line863"></a> *     If the key is not found, this will have length 0, but never be null.
<a name="line864"></a> */
<a name="line865"></a>goog.uri.utils.getParamValues = function(uri, keyEncoded) {
<a name="line866"></a>  var hashOrEndIndex = uri.search(goog.uri.utils.hashOrEndRe_);
<a name="line867"></a>  var position = 0;
<a name="line868"></a>  var foundIndex;
<a name="line869"></a>  var result = [];
<a name="line870"></a>
<a name="line871"></a>  while ((foundIndex = goog.uri.utils.findParam_(
<a name="line872"></a>      uri, position, keyEncoded, hashOrEndIndex)) &gt;= 0) {
<a name="line873"></a>    // Find where this parameter ends, either the &#39;&amp;&#39; or the end of the
<a name="line874"></a>    // query parameters.
<a name="line875"></a>    position = uri.indexOf(&#39;&amp;&#39;, foundIndex);
<a name="line876"></a>    if (position &lt; 0 || position &gt; hashOrEndIndex) {
<a name="line877"></a>      position = hashOrEndIndex;
<a name="line878"></a>    }
<a name="line879"></a>
<a name="line880"></a>    // Progress forth to the end of the &quot;key=&quot; or &quot;key&amp;&quot; substring.
<a name="line881"></a>    foundIndex += keyEncoded.length + 1;
<a name="line882"></a>    // Use substr, because it (unlike substring) will return empty string
<a name="line883"></a>    // if foundIndex &gt; position.
<a name="line884"></a>    result.push(goog.string.urlDecode(uri.substr(
<a name="line885"></a>        foundIndex, position - foundIndex)));
<a name="line886"></a>  }
<a name="line887"></a>
<a name="line888"></a>  return result;
<a name="line889"></a>};
<a name="line890"></a>
<a name="line891"></a>
<a name="line892"></a>/**
<a name="line893"></a> * Regexp to find trailing question marks and ampersands.
<a name="line894"></a> * @type {RegExp}
<a name="line895"></a> * @private
<a name="line896"></a> */
<a name="line897"></a>goog.uri.utils.trailingQueryPunctuationRe_ = /[?&amp;]($|#)/;
<a name="line898"></a>
<a name="line899"></a>
<a name="line900"></a>/**
<a name="line901"></a> * Removes all instances of a query parameter.
<a name="line902"></a> * @param {string} uri The URI to process.  Must not contain a fragment.
<a name="line903"></a> * @param {string} keyEncoded The URI-encoded key.
<a name="line904"></a> * @return {string} The URI with all instances of the parameter removed.
<a name="line905"></a> */
<a name="line906"></a>goog.uri.utils.removeParam = function(uri, keyEncoded) {
<a name="line907"></a>  var hashOrEndIndex = uri.search(goog.uri.utils.hashOrEndRe_);
<a name="line908"></a>  var position = 0;
<a name="line909"></a>  var foundIndex;
<a name="line910"></a>  var buffer = [];
<a name="line911"></a>
<a name="line912"></a>  // Look for a query parameter.
<a name="line913"></a>  while ((foundIndex = goog.uri.utils.findParam_(
<a name="line914"></a>      uri, position, keyEncoded, hashOrEndIndex)) &gt;= 0) {
<a name="line915"></a>    // Get the portion of the query string up to, but not including, the ?
<a name="line916"></a>    // or &amp; starting the parameter.
<a name="line917"></a>    buffer.push(uri.substring(position, foundIndex));
<a name="line918"></a>    // Progress to immediately after the &#39;&amp;&#39;.  If not found, go to the end.
<a name="line919"></a>    // Avoid including the hash mark.
<a name="line920"></a>    position = Math.min((uri.indexOf(&#39;&amp;&#39;, foundIndex) + 1) || hashOrEndIndex,
<a name="line921"></a>        hashOrEndIndex);
<a name="line922"></a>  }
<a name="line923"></a>
<a name="line924"></a>  // Append everything that is remaining.
<a name="line925"></a>  buffer.push(uri.substr(position));
<a name="line926"></a>
<a name="line927"></a>  // Join the buffer, and remove trailing punctuation that remains.
<a name="line928"></a>  return buffer.join(&#39;&#39;).replace(
<a name="line929"></a>      goog.uri.utils.trailingQueryPunctuationRe_, &#39;$1&#39;);
<a name="line930"></a>};
<a name="line931"></a>
<a name="line932"></a>
<a name="line933"></a>/**
<a name="line934"></a> * Replaces all existing definitions of a parameter with a single definition.
<a name="line935"></a> *
<a name="line936"></a> * Repeated calls to this can exhibit quadratic behavior due to the need to
<a name="line937"></a> * find existing instances and reconstruct the string, though it should be
<a name="line938"></a> * limited given the 2kb limit.  Consider using appendParams to append multiple
<a name="line939"></a> * parameters in bulk.
<a name="line940"></a> *
<a name="line941"></a> * @param {string} uri The original URI, which may already have query data.
<a name="line942"></a> * @param {string} keyEncoded The key, which must already be URI encoded.
<a name="line943"></a> * @param {*} value The value, which will be stringized and encoded (assumed
<a name="line944"></a> *     not already to be encoded).
<a name="line945"></a> * @return {string} The URI with the query parameter added.
<a name="line946"></a> */
<a name="line947"></a>goog.uri.utils.setParam = function(uri, keyEncoded, value) {
<a name="line948"></a>  return goog.uri.utils.appendParam(
<a name="line949"></a>      goog.uri.utils.removeParam(uri, keyEncoded), keyEncoded, value);
<a name="line950"></a>};
<a name="line951"></a>
<a name="line952"></a>
<a name="line953"></a>/**
<a name="line954"></a> * Generates a URI path using a given URI and a path with checks to
<a name="line955"></a> * prevent consecutive &quot;//&quot;. The baseUri passed in must not contain
<a name="line956"></a> * query or fragment identifiers. The path to append may not contain query or
<a name="line957"></a> * fragment identifiers.
<a name="line958"></a> *
<a name="line959"></a> * @param {string} baseUri URI to use as the base.
<a name="line960"></a> * @param {string} path Path to append.
<a name="line961"></a> * @return {string} Updated URI.
<a name="line962"></a> */
<a name="line963"></a>goog.uri.utils.appendPath = function(baseUri, path) {
<a name="line964"></a>  goog.uri.utils.assertNoFragmentsOrQueries_(baseUri);
<a name="line965"></a>
<a name="line966"></a>  // Remove any trailing &#39;/&#39;
<a name="line967"></a>  if (goog.string.endsWith(baseUri, &#39;/&#39;)) {
<a name="line968"></a>    baseUri = baseUri.substr(0, baseUri.length - 1);
<a name="line969"></a>  }
<a name="line970"></a>  // Remove any leading &#39;/&#39;
<a name="line971"></a>  if (goog.string.startsWith(path, &#39;/&#39;)) {
<a name="line972"></a>    path = path.substr(1);
<a name="line973"></a>  }
<a name="line974"></a>  return goog.string.buildString(baseUri, &#39;/&#39;, path);
<a name="line975"></a>};
<a name="line976"></a>
<a name="line977"></a>
<a name="line978"></a>/**
<a name="line979"></a> * Standard supported query parameters.
<a name="line980"></a> * @enum {string}
<a name="line981"></a> */
<a name="line982"></a>goog.uri.utils.StandardQueryParam = {
<a name="line983"></a>
<a name="line984"></a>  /** Unused parameter for unique-ifying. */
<a name="line985"></a>  RANDOM: &#39;zx&#39;
<a name="line986"></a>};
<a name="line987"></a>
<a name="line988"></a>
<a name="line989"></a>/**
<a name="line990"></a> * Sets the zx parameter of a URI to a random value.
<a name="line991"></a> * @param {string} uri Any URI.
<a name="line992"></a> * @return {string} That URI with the &quot;zx&quot; parameter added or replaced to
<a name="line993"></a> *     contain a random string.
<a name="line994"></a> */
<a name="line995"></a>goog.uri.utils.makeUnique = function(uri) {
<a name="line996"></a>  return goog.uri.utils.setParam(uri,
<a name="line997"></a>      goog.uri.utils.StandardQueryParam.RANDOM, goog.string.getRandomString());
<a name="line998"></a>};
</pre>


</body>
</html>
